import random
from django_redis import get_redis_connection
from django.http import HttpResponse, JsonResponse

from django.views import View
from libs.captcha.captcha import captcha
from meiduo_mall.settings.dev import logger
from celery_tasks.sms.tasks import send_sms_code

"""
功能:
    处理图片验证码
触发时刻:
    在输入网址(/register)和点击pic_code字段,触发generate_image_code函数发送该url
请求方法:
    GET
请求url:
    0, image_codes/(?P<uuid>[\w-]+)/
流程:
    1, 获取查询字符串中的参数uuid,并且通过正则进行效验
    2, 通过第三方工具captcha获得图片验证码
    3, 将图片验证码存放在redis数据库中,设置键是img_uuid, 过期时间5分钟,值是图片验证码中的数值
    4, 返回给前端图片,并设置格式为image/jpge
"""
class ImageCodeView(View):
    def get(self, request, uuid):
        # 1, 通过正则效验uuid

        # 2, 生成图片验证码
        text, image_code = captcha.generate_captcha()
        print("图片验证码是:", text)

        # 3, 将图片验证码存放在redis数据库中
        image_redis_client = get_redis_connection("verify_image_code")
        image_redis_client.setex("img_%s" % uuid, 300, text)

        return HttpResponse(image_code, content_type="image/jpeg")



"""
功能:
    处理短信验证码
触发时刻:
    在点击msg_code字段,触发send_sms_code函数发送该url
请求方法:
    GET
请求url:
    0, sms_codes/(?P<mobile>1[3-9]\d{9})/
流程:
    1, 获取查询字符串中的参数mobile,并且通过正则进行效验
    2, 获取用户输入的image_code和前端发送过来的image_code_id
    3, 判断图片验证码是否为空
    4, 取出在redis数据库中存储的图片验证码的值,与用户输入的image_code进行对比,
    5, 对比正确,则使用random函数 "%06d" 生成6位数验证码
    6, 从redis数据库中获取send_flag, 如果获取到了,则返回验证码发送过于频繁,
    7, 如果没有获取到,在redis中存放一个键是send_flag, 过期时间为60s, 值随意的一个键值对
    8, 通过荣联运发送短信验证码
    9, 发送成功后,将短信验证码存放在redis数据库中
"""
class SMSCodeView(View):

    def get(self, request, mobile):
        # 1, 接收用户写的图片验证码和前端产生的uuid
        image_code = request.GET.get("image_code")
        uuid = request.GET.get("image_code_id")

        try:
            # 2, 判断是否为空,以及是否与数据库中存储的图片验证码一致
            image_redis_client = get_redis_connection("verify_image_code")
            redis_image_code = image_redis_client.get("img_%s" % uuid)

            if not redis_image_code:
                return JsonResponse({"code": 4001, "errmsg": "图片验证码不存在"})

            if redis_image_code.decode().lower() != image_code.lower():
                return JsonResponse({"code": 4001, "errmsg": "图片验证码错误"})

            # 图片验证码效验成功,删除之前的图片验证码
            image_redis_client.delete("img_%s" % uuid)
        except Exception as e:
            logger.error(e)

        # 生成短信验证码
        sms_code = "%06d" % random.randint(0, 999999)

        # 避免频发发送图片验证码
        sms_code_redis = get_redis_connection("sms_code")
        send_flag = sms_code_redis.get("send_flag_%s" % mobile)

        if send_flag:
            return JsonResponse({"code": 4002, "errmsg": "发送短信过于频繁!!!"})
        # 将短信验证码存放在redis数据中
        try:
            # 这里的键是 send_flag, 过期时间是60s, 值是一个随意的值
            # 在这里使用pipeline进行redis数据库的优化
            p1 = sms_code_redis.pipeline()
            p1.setex("send_flag_%s" % mobile, 60, 1)
            p1.setex("sms_%s" % mobile, 300, sms_code)
            # 执行管道
            p1.execute()
        except Exception as e:
            logger.error(e)

        # 借助第三方,发送短信验证码(这里交给celery异步任务来做)
        send_sms_code.delay(mobile, sms_code)

        return JsonResponse({"code": "0", "errmsg": "发送短信成功!"})
